package com.qingcloud.adminbackend.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qingcloud.adminbackend.constant.WamingConstant;
import com.qingcloud.adminbackend.entity.eid.*;
import com.qingcloud.adminbackend.exception.WmCommonException;
import com.qingcloud.adminbackend.entity.domain.SysDomain;
import com.qingcloud.adminbackend.entity.eid.*;
import com.qingcloud.adminbackend.entity.stationgroup.SysStationGroup;
import com.qingcloud.adminbackend.enums.EidBatchStatusEnum;
import com.qingcloud.adminbackend.enums.ProductTypeEnum;
import com.qingcloud.adminbackend.mapper.SysDomainMapper;
import com.qingcloud.adminbackend.mapper.SysEquipmentidGenMapper;
import com.qingcloud.adminbackend.mapper.SysEquipmentidListMapper;
import com.qingcloud.adminbackend.mapper.SysUserMapper;
import com.qingcloud.adminbackend.service.ISysEquipmentidGenService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.IntStream;

/**
 * <p>
 * 设备编号生成 服务实现类
 * </p>
 *
 * @author wangjinnan
 * @since 2019-04-17
 */
@Service
public class SysEquipmentidGenServiceImpl extends ServiceImpl<SysEquipmentidGenMapper, SysEquipmentidGen> implements ISysEquipmentidGenService {

    @Resource
    private SysEquipmentidListMapper sysEquipmentidListMapper;

    @Resource
    private SysDomainMapper sysDomainMapper;

    @Resource
    private SysUserMapper sysUserMapper;

    //唯一ID生成工具
    private Snowflake snowflake = IdUtil.createSnowflake(6, 6);

    /**
     * 生成设备编号
     *
     * @param eidGenParam
     * @param userId
     * @return 设备编号批次ID
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String create(EidGenParam eidGenParam, String userId) {
        //初始化对象
        SysEquipmentidGen sysEquipmentidGen = new SysEquipmentidGen();
        sysEquipmentidGen.setId(snowflake.nextIdStr());
        sysEquipmentidGen.setBatchCount(eidGenParam.getBatchCount());
        sysEquipmentidGen.setCreateBy(userId);
        sysEquipmentidGen.setDomainId(eidGenParam.getDomainId());
        sysEquipmentidGen.setProduct(eidGenParam.getProduct());
        //初始化设备ID
        long eidStart = 0;
        //根据产品类型找到最大的设备编号
        String maxId = baseMapper.findMaxByProduct(eidGenParam.getProduct(), eidGenParam.getDomainId());
        if (StrUtil.isBlank(maxId)) {
            //没有最大编号，使用初始编号，每种产品类型初始编号不同
            eidStart = getInitEid(eidGenParam.getProduct(), eidGenParam.getDomainId());
        } else {
            //室内产品时，判断最大ID和当前年月是否一样
            if (eidGenParam.getProduct() == ProductTypeEnum.AIR_COMMON.code
                    || eidGenParam.getProduct() == ProductTypeEnum.DECORATION.code) {
                String yearMonth = LocalDate.now().format(DateTimeFormatter.ofPattern("yyMM"));
                //
                if (yearMonth.equals(maxId.substring(1, 5))) {
                    eidStart = Long.valueOf(maxId) + 1;
                } else {
                    eidStart = getInitEid(eidGenParam.getProduct(), eidGenParam.getDomainId());
                }
            } else {
                eidStart = Long.valueOf(maxId) + 1;
            }
        }
        //判断结束ID是否超限
        long tempEnd = eidStart + eidGenParam.getBatchCount() - 1;
        isOver(eidGenParam.getProduct(), eidStart, tempEnd);
        //生成连续编号
        sysEquipmentidGen.setEidStart(String.valueOf(eidStart));
        long finalEidStart = eidStart;
        //存储设备号对象
        List<SysEquipmentidList> eidList = new ArrayList<>(eidGenParam.getBatchCount());
        IntStream.range(0, eidGenParam.getBatchCount()).forEach(idx -> {
            SysEquipmentidList eid = new SysEquipmentidList();
            eid.setBatchId(sysEquipmentidGen.getId());
            eid.setProduct(eidGenParam.getProduct());
            eid.setEquipmentId(String.valueOf(finalEidStart + idx));
            eidList.add(eid);
        });
        //获取结束设备编号
        sysEquipmentidGen.setEidEnd(eidList.get(eidList.size() - 1).getEquipmentId());
        //入库
        baseMapper.insert(sysEquipmentidGen);
        //批量插入sql长度问题，mysql配置加大max_allowed_packet
        sysEquipmentidListMapper.insertBatch(eidList);
        return sysEquipmentidGen.getId();
    }

    /**
     * 根据产品和城市获取初始编号
     *
     * @param product  产品
     * @param domainId 城市编号
     * @return
     */
    private long getInitEid(int product, Integer domainId) {
        if (product == ProductTypeEnum.AIR_COMMON.code) {
            //室内通用设备
            String yearMonth = LocalDate.now().format(DateTimeFormatter.ofPattern("yyMM"));
            return Long.valueOf(ProductTypeEnum.AIR_COMMON.idStart + yearMonth + "00001");
        } else if (product == ProductTypeEnum.DECORATION.code) {
            //装修设备
            String yearMonth = LocalDate.now().format(DateTimeFormatter.ofPattern("yyMM"));
            return Long.valueOf(ProductTypeEnum.DECORATION.idStart + yearMonth + "00001");
        } else {
            //室外设备
            //查询城市区号
            String phoneCode = sysDomainMapper.findPhoneCode(domainId);
            if (StrUtil.isBlank(phoneCode)) {
                throw new WmCommonException(domainId + "未配置电话区号");
            }
            return Long.valueOf(ProductTypeEnum.OTHER.idStart + phoneCode + "0001");
        }
    }

    /**
     * 根据产品和城市获取初始编号
     *
     * @param product 产品
     * @return
     */
    private void isOver(int product, long eidStart, long eidEnd) {
        if (product == ProductTypeEnum.AIR_COMMON.code || product == ProductTypeEnum.DECORATION.code) {
            //室内设备后5位要大于开始，小于等于99999
            int startLast = Integer.valueOf(String.valueOf(eidStart)
                    .substring(String.valueOf(eidStart).length() - 5, String.valueOf(eidStart).length()));
            int endLast = Integer.valueOf(String.valueOf(eidEnd)
                    .substring(String.valueOf(eidEnd).length() - 5, String.valueOf(eidEnd).length()));
            if (endLast < startLast || startLast < 1) {
                throw new WmCommonException("生成数量已达本年月设备编号最大，请联系管理员");
            }
        } else {
            //室内设备后4位要大于开始，小于等于9999
            int startLast = Integer.valueOf(String.valueOf(eidStart)
                    .substring(String.valueOf(eidStart).length() - 4, String.valueOf(eidStart).length()));
            int endLast = Integer.valueOf(String.valueOf(eidEnd)
                    .substring(String.valueOf(eidEnd).length() - 4, String.valueOf(eidEnd).length()));
            if (endLast < startLast || startLast < 1) {
                throw new WmCommonException("生成数量已达本地区设备编号最大，请联系管理员");
            }
        }
    }

    /**
     * 分页查询设备编号批次
     *
     * @param pageParam
     * @return
     */
    @Override
    public IPage<EidBatchPageDTO> searchPage(EidBatchPageParam pageParam) {
        //省市区域对象
        List<SysDomain> domainList = sysDomainMapper.selectList(new QueryWrapper<SysDomain>().eq("city_type", 1).or().eq("city_type", 2));
        Map<String, String> domainMap = new HashMap<>(domainList.size());
        domainList.forEach(domain -> domainMap.put(String.valueOf(domain.getId()), domain.getDomainName()));
        //框架分页参数对象
        Page<SysStationGroup> page = new Page<>(pageParam.getCurrentPage(), pageParam.getPerPage());
        //设备编号参数查询批次ID
        if (StrUtil.isNotBlank(pageParam.getEquipmentId())) {
            //设备编号不为空的时候，先通过设备编号查询出批次编号
            pageParam.setBatchIdList(sysEquipmentidListMapper.findBatchIdLikeEquipmentId(pageParam.getEquipmentId()));
            //如果没找到批次ID，要返回空数据
            if (CollUtil.isEmpty(pageParam.getBatchIdList())) {
                return new Page<>();
            }
        }
        //操作人ID列表
        if (StrUtil.isNotBlank(pageParam.getOperator())) {
            //操作人参数不为空时，查询操作人编号
            pageParam.setUserIdList(sysUserMapper.findIdLikeName(pageParam.getOperator()));
            //如果没找到用户ID，要返回空数据
            if (CollUtil.isEmpty(pageParam.getUserIdList())) {
                return new Page<>();
            }
        }
        IPage<EidBatchPageDTO> dtoPage = baseMapper.searchPage(page, pageParam);
        dtoPage.getRecords().forEach(it -> {
            //状态
            it.setBatchStatus(EidBatchStatusEnum.getNameByCode(it.getBatchStatusFlag()));
            //省市
            if (StrUtil.isNotBlank(it.getDomainId())) {
                it.setDomain(domainMap.get(it.getDomainId().substring(0, 2) + "0000") + "/" + domainMap.get(it.getDomainId()));
            }
        });
        return dtoPage;
    }

    /**
     * 作废编号批次
     *
     * @param id     批次ID
     * @param userId 操作用户ID
     */
    @Override
    public void cancel(String id, String userId) {
        SysEquipmentidGen gen = new SysEquipmentidGen();
        //默认数据置空，因为null字段不会设置到数据库
        gen.setCreateDt(null);
        //设置作废参数
        gen.setBatchStatus(EidBatchStatusEnum.CANCEL.code);
        gen.setId(id);
        gen.setCancelBy(userId);
        gen.setCancelDt(LocalDateTime.now().format(WamingConstant.NORMAL_FULL_FORMATTER));
        baseMapper.updateById(gen);
    }
}
